
#include <stdint.h>
#include <stdbool.h>
#include "socket.h"
#ifndef NONUSER_GLIB
#include <gio/gio.h>
#include <glib.h>
typedef int (*func_send)(void *, const uint8_t *, size_t, void *);
static void print_hex(const uint8_t *buffer, size_t size)
{
  gsize i;

  for(i = 0; i < size; i++) {
    g_print("%02x ", (unsigned char)buffer[i]);
  }
  g_print("\n");
}
//udp
void *udp_open(const char *ip, int port)
{
  GObject *self = NULL;
  GSocket *socket = NULL;
  GError *error = NULL;
  GInetAddress *addr = NULL;
  GSocketAddress *saddr = NULL;

  socket = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
      0, &error);
  addr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
  saddr = g_inet_socket_address_new(addr, port);
  g_socket_bind(socket, saddr, TRUE, &error);

  self = G_OBJECT(socket_socket_new());
  g_debug("L%d f-%s %s[%d]socket:%p", __LINE__, __func__,
      ip, port, socket);
  g_object_set(self, "socket", socket, "ip", ip, "port", port,
      NULL);
  gint bufferSize = 4096;
  gpointer buffer = calloc(1, bufferSize);
  g_object_set(self, "buffer", buffer, "bufferSize", bufferSize, NULL);
  return self;
}
void *udp_send(void *object, void *address, const char *buffer, size_t size)
{
  GObject *self = object;
  GSocket *socket = NULL;
  GError *error = NULL;
  gssize ssize = 0;

  g_object_get(self, "socket", &socket, NULL);
  ssize = g_socket_send_to(socket, address, buffer, size, NULL, &error);
  if (ssize) {
    print_hex((uint8_t *)buffer, ssize);
  }
  return (void *)ssize;
}
void *net_address_create(const char *ip, int port)
{
  GInetAddress *addr = NULL;
  GSocketAddress *saddr = NULL;

  addr = g_inet_address_new_from_string(ip);
  saddr = g_inet_socket_address_new(addr, port);

  return saddr;
}
void *udp_read(void *object)
{
  GObject *self = object;
  GSocketAddress *sa;
  GSocket *socket;
  gint bufferSize;
  gchar *buffer;
  gssize nread;
  GError *error = NULL;

  g_object_get(self, "socket", &socket,
      "buffer", &buffer, "bufferSize", &bufferSize, NULL);
  nread = g_socket_receive_from(socket, &sa, buffer, bufferSize, NULL,
      &error);
  if (error && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
    g_clear_error (&error);
    return NULL;
  }
  g_object_set(self, "nread", nread, "clientAddress", sa, NULL);
  //g_print("++++[%"G_GSIZE_FORMAT"]:", nread);
  //print_hex((uint8_t *)buffer, nread);
  return buffer;
}
int udp_read_to_serial_handle(void *user_data)
{
  g_debug("L%d f-%s", __LINE__, __func__);
  GError *error = NULL;
  gsize bytes_read, bytes_write;
  GObject *self = user_data;
  GSocket *socket = NULL;
  gchar *buffer;
  gint bufferSize;

  g_object_get(self, "socket", &socket,
      "buffer", &buffer, "bufferSize", &bufferSize, NULL);
  bytes_read = g_socket_receive(socket, buffer, bufferSize,
      NULL, &error);
  if (bytes_read) {
    print_hex((uint8_t *) buffer, bytes_read);
    GIOChannel *channel = NULL;
    func_send handle;
    g_object_get(self, "channel", &channel, "funcPrefixSend", &handle,
        NULL);
    uint8_t *new_data = NULL;
    size_t new_size = 0;
    if (handle) {
      handle(channel, (uint8_t *)buffer, bufferSize, self);
      new_data = (uint8_t *)buffer;
      new_size = bytes_read;
    } else {
      new_data = (uint8_t *)buffer;
      new_size = bytes_read;
    }
    g_io_channel_write_chars(channel, (gchar *)new_data, new_size,
        &bytes_write, &error);
    if (error) {
      g_warning("L%d f-%s error:%s", __LINE__, __func__,
          error->message);
      g_clear_error(&error);
      return 0;
    } else if (bytes_read == bytes_write) {
      print_hex((uint8_t *)new_data, new_size);
      g_io_channel_flush(channel, &error);
      if (error) {
        g_warning("L%d f-%s error:%s", __LINE__, __func__,
            error->message);
        g_clear_error(&error);
        return 0;
      }
    } else {
      g_warning(
          "L%d f-%s bytes not all:%"G_GSIZE_FORMAT",%"G_GSIZE_FORMAT,
          __LINE__, __func__, bytes_read, bytes_write);
      exit(1);
    }
  }
  return true;
}
/*
void udp_to_serial_handle(void *obj, void *serial, void *handle, void *user_data)
{
  GObject *self = obj;

  g_object_set(self, "channel", serial, "funcPrefixSend", handle,
      "data", user_data, NULL);

  //guint timeout_id = 0;
  g_timeout_add(100, udp_read_to_serial_handle, self);
}
*/
#else
/**
 * @brief   UDP服务端
 * @author  Mculover666
 * @date    2020/04/15
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

void *udp_open(char *ip, int port)
{
  int server_sock_fd;
  struct sockaddr_in server_addr, client_addr;
  char recv_buf[100];
  int nbytes = 0;
  socklen_t len = 0;

  server_sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (server_sock_fd < 0)
  {
      printf("服务端Socket创建失败");
      return -1;
  }
  printf("服务端Socket创建成功\n");

  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(port);
  bind(server_sock_fd,
      (struct sockaddr *) &server_addr, sizeof(server_addr));
  printf("服务端Socket绑定成功\n");
  while(1)
  {
      /* 接收UDP客户端的数据 */
      printf("等待接收客户端数据：\n");
      len = sizeof(client_addr);
      recv_buf[nbytes] = '\0';
      printf("recv %d bytes:%s.\n", nbytes, recv_buf);

      //接收用户输入，发送给客户端
      printf("请输入要发送给客户端的数据:");
      fgets(recv_buf, 100, stdin);
      sendto(server_sock_fd,recv_buf,strlen(recv_buf),0,(struct sockaddr *)&client_addr,len);
  }

  return 0;
}
void *udp_read(void *object)
{
  nbytes = recvfrom(server_sock_fd, recv_buf, 100, 0, (struct sockaddr *)&client_addr, &len);
  printf("ok\n");
}

#endif
